/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package biofilter.pipelines;

import biofilter.factories.MappedPositionFactory;
import biofilter.filters.HistogramFilter;
import biofilter.filters.RecordsFile2GFF;
import biofilter.filters.RecordsFile2MappedPosition;
import biofilter.records.HistogramRecord;
import biofilter.records.Record;
import biofilter.sources.RecordsFile;
import biofilter.util.MappedPosition;
import biofilter.util.ProcessUtil;
import biofilter.util.SystemProperties;
import java.io.IOException;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

/**
 *
 * @author Daniel Quest
 * @date   March 5 2010
 * The idea for the MappedPositionHistoPipeline is to remove the need for BowtieHistoPipeline AND Mapper454HistoPipeline
 * This class will be more generic and perform both of those functions!
 *
 */
public class MappedPositionHistoPipeline implements PipelineIF {

    private RecordsFile fnrf = null;
    private HistogramFilter histoF = null;
    private RecordsFile2GFF rf2gff = null;
    private ProcessUtil pu = new ProcessUtil();
    private SystemProperties sp = null;
    public MappedPositionHistoPipeline(){
    }

    private int readsMapped;
    private int basesMapped;
    private void init(){
        try {            
            //General Utility Class Setup:
            sp = new SystemProperties();
            readsMapped = 0;
            basesMapped = 0;

            //Pipes and Filters for building the histogram.
            this.fnrf = new RecordsFile(this.infile, "biofilter.records.FileNameRecord");
            //Logger.getLogger(Mapper454HistoPipeline.class.getName()).log(Level.INFO, "Mapped Read File: " + fileNameRecordsFile);
            rf2gff = new RecordsFile2GFF();
            rf2gff.setSource(this.fnrf);
            histoF = new HistogramFilter();
            histoF.setMapMax(this.chopVal);
            histoF.setSource(rf2gff);
            
        } catch (IOException ex) {
            Logger.getLogger(MappedPositionHistoPipeline.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    private void updateCount(MappedPosition mp){
        readsMapped++;
        basesMapped += mp.length();
    }

    /**
     *
     * @param mpType = the type of mapped position records input to the pipeline
     * e.g. biofilter.records.GFFRecord
     */
    String mappedPositionType = null;
    public void setMappedPositionType(String mpType){
        this.mappedPositionType = mpType;
        rf2gff.setMappedPositionType(this.mappedPositionType);
    }

    /*
     * mapMax is the maximum value that will be mapped to the histogram.
     * For example if ribosomalRNA has 50,000 reads and map max = 200 then
     * the region over the ribosomalRNA genes will only be 200 NOT 50,000
     * This will not effect the total number of mapped reads or mapped basepairs.
     */
    private int mapmax = Integer.MAX_VALUE;
    public void setMapMax(int mm){
        this.mapmax = mm;
    }

    private String outputDir = null;
    private String targetDatabase = "";

    public String getOutputDir() {
        return outputDir;
    }

    public void setOutputDir(String outputDir) {
        if (!outputDir.endsWith("/")) outputDir = outputDir + "/";
        this.outputDir = outputDir;
    }

    private String infile;
    private String outfile;
    private int chopVal;
    protected Options options = null;
    public void setup(String [] args) throws org.apache.commons.cli.ParseException{
            Double dd = new Double("0");
            options = new Options();
            //Setup Options
            //Boolean Options
            Option help = new Option( "h", "help", false, "print help message" );

            //Param Options
            Option in   = new Option("i", "infile", true, "This file contains paths to mapped reads files" );
            Option out   = new Option("o", "outfile", true, "Output file for profile (two stranded file for #hits/bp along genome" );
            Option mapper = new Option("m", "mapper", true, "Mapper Used e.g. GSMapper454, bowtie, blast (Default GFF records)" );
            Option coverage = new Option("c", "coverage", true, "Regions with coverage above this value instead have input value e.g. -c 100 chopps everything off at 100 (default infinity)" );

            //Add command line options to influence behavior
            options.addOption( help );
            options.addOption(in);
            options.addOption(out);
            options.addOption(mapper);
            options.addOption(coverage);

            System.out.println("Input Command: ");
            for(int i=0; i<args.length;i++)
                System.out.print(args[i]);
            System.out.print("\n");
            CommandLineParser parser = new GnuParser();
            CommandLine cmd = parser.parse( options, args);
            //String[] parsed = cmd.getArgs();
            //for(int i=0;i<parsed.length;i++){
            //    System.err.println(parsed[i]);
            //}

            //Logic to handle standard command line options such as help
            if (cmd.hasOption("help") == true || cmd.hasOption("infile") == false){
                // automatically generate the help statement
                HelpFormatter formatter = new HelpFormatter();
                formatter.printHelp( "SeqGenOpts", options );
                System.exit(0);
            }
            //Set the path to the path containg path locations of read files.
            if(cmd.hasOption("infile")){
                this.infile = cmd.getOptionValue("infile");
                Logger.getLogger(StartSitePipeline.class.getName()).log(Level.INFO, "Input Paths File (references to reads): " + this.infile, this.infile);
            }
            //Set the path to the path containg path locations of read files.
            if(cmd.hasOption("outfile")){
                this.outfile = cmd.getOptionValue("outfile");
                Logger.getLogger(StartSitePipeline.class.getName()).log(Level.INFO, "Output File: " + this.outfile, this.outfile);
            }

            if(cmd.hasOption("coverage")){
                this.chopVal = Integer.parseInt( cmd.getOptionValue("coverage") );
            }Logger.getLogger(StartSitePipeline.class.getName()).log(Level.INFO, "Values in the profile will be chopped if larger than: " + this.chopVal, this.chopVal);

            init();
            if(cmd.hasOption('m') ){
                if(cmd.getOptionValue('m').equalsIgnoreCase("GSMapper454")){
                    rf2gff.setMappedPositionType("biofilter.records.Mapper454Record");
                }else if(cmd.getOptionValue('m').equalsIgnoreCase("bowtie")){
                    rf2gff.setMappedPositionType("biofilter.records.BowTieRecord");
                }else if(cmd.getOptionValue('m').equalsIgnoreCase("blast")){
                    rf2gff.setMappedPositionType("biofilter.records.BlastTabRecord");
                }else if(cmd.getOptionValue('m').equalsIgnoreCase("GFF")){
                    rf2gff.setMappedPositionType("biofilter.records.GFFRecord");
                }
            }else{
                rf2gff.setMappedPositionType("biofilter.records.GFFRecord");
            }
            //System.err.println("Start Site Pipeline 112, mappedPositionType :" + rf2mp.getMappedPositionType());
    }

    public static void main(String[] args) {
        try {

            String[] arguments = new String[9];
            arguments[0] = "StartSitePipeline";
            arguments[1] = "-m";
            arguments[2] = "bowtie";
            arguments[3] = "-c";
            arguments[4] = "100";
            arguments[5] = "-i";
            arguments[6] = "/auto/transcriptomics/runfiles/Rhodopseudomonas_palustris_CGA009/pool_A_NC_005297.run";
            //arguments[6] = "/auto/transcriptomics/runfiles/Clostridium_thermocellum_ATCC_27405/ALLSMASHED.run";
            arguments[7] = "-o";
            arguments[8] = "/auto/transcriptomics/runfiles/Rhodopseudomonas_palustris_CGA009/pool_A_NC_005297.profile";
            System.out.println("Starting Profile Generation Pipeline: ");
            MappedPositionHistoPipeline mpp = new MappedPositionHistoPipeline();
            mpp.setup(arguments);
            mpp.execPipeline();
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }
    
        @Override
    public Vector<Record> execPipeline() throws Exception {
        
        //Below is an example of getting the raw positions out of an arbitrary set of files
        //while(!rf2gff.eof()){
        //    Record r = rf2gff.getRecord();
        //    System.err.print(r.get());
        //}

        //Below is an example of creating a histogram from a set of reads...
        //while(!histoF.eof()){
        //    Logger.getLogger(StartSitePipeline.class.getName()).log(Level.INFO, "Constructing Profile... ");
        //    Record r = histoF.getRecord();
            //System.err.print(r.get());
        //}

        /*
        while(!this.anno2gff.eof()){
            Record r = anno2gff.getRecord();
            System.err.print(r.get());
        }
         * */

        /*
         * This loop goes through the annotation...
        while(!this.annGFF.eof()){
            GFFRecord gff = (GFFRecord) this.annGFF.getRecord();
            System.err.println(gff.get());
        }
         * */

        
        while(!histoF.eof()){
            Logger.getLogger(StartSitePipeline.class.getName()).log(Level.INFO, "Constructing Profile... ");
            HistogramRecord hr = (HistogramRecord) histoF.getRecord();
            hr.toFile(this.outfile);
            Logger.getLogger(StartSitePipeline.class.getName()).log(Level.INFO, "Finished, Thanks for Using!\n ");
        }//end while histoEOF


        return null;
        /*
        Vector<Record> resultFiles = new Vector<Record>();
        HistogramRecord hr = new HistogramRecord();
        hr.setMapMax(this.mapmax);
        MappedPosition mr = (MappedPosition) rf2mp.getRecord();
        updateCount(mr);
        while (mr != null){
            hr.map(mr.getStart(), mr.getEnd(), mr.getStrand(), 1.0);
            this.updateCount(mr);
            mr = (MappedPosition) rf2mp.getRecord();
        }
        String outfile = this.outputDir + pu.getUniqueFileName(targetDatabase + ".hist");
        Logger.getLogger( Mapper454HistoPipeline.class.getName() ).log(Level.INFO, "Printing Histogram to: " + outfile);
        hr.toFile(outfile);
        return resultFiles; //problem! this is empty!
         * */
    }

}
